package compoundDB.io;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class IOController {

	private static List<MoleculeReader> readers;
	private static List<MoleculeWriter> writers;
	
	static {
		loadPlugins();
	}
	
	/**
	 * Forces a load of all IO plugins in the /plugins/ folder of the distribution.
	 * This is called automatically when the IOController class is first accessed,
	 *  but can be called manually to force a load, of to check for new plugins
	 *  without restarting the application.
	 */
	public static void loadPlugins() {
		readers = new LinkedList<MoleculeReader>();
		writers = new LinkedList<MoleculeWriter>();
		
		File f = new File("plugins/");
		System.out.println("Plugin folder: " + f.getAbsolutePath());
		String[] files = f.list();
		
		System.out.println("Found " + files.length + " potential plugins");
		int count = 0;
		try {
			ClassLoader cl = new URLClassLoader(new URL[]{f.toURI().toURL()});
			
			for(String s : files) {
				String ext = s.substring(s.lastIndexOf("."));
				if(!ext.equals(".class")) {
					continue;
				}
				s = s.substring(0, s.lastIndexOf(".")); //Strip off ".class" from the end
				Class<?> c = null;
				try {
					c = cl.loadClass(s);
					List<Class<?>> iList = Arrays.asList(c.getInterfaces());
					Object item = null;
					boolean plugin = false;
					if(iList.contains(MoleculeReader.class)) {
						item = c.newInstance();
						readers.add((MoleculeReader)item);
						plugin = true;
					}
					if(iList.contains(MoleculeWriter.class)) {
						if(item == null)
							item = c.newInstance();
						writers.add((MoleculeWriter)item);
						plugin = true;
					}
					if(plugin)
						count++;
				} catch (Exception e) {
					System.err.println("Error instantiating " + s);
					continue;
				}
			}
		} catch (NullPointerException e) {
			System.err.println("No plugin directory");
		} catch (Exception e) {
			System.err.println("Error while loading plugins");
		}
		System.out.println("Found " + count + " I/O plugins:");
		System.out.println("\t" + readers.size() + " readers");
		System.out.println("\t" + writers.size() + " writers");
	}
	
	/**
	 * Gets a MoleculeReader capable of reading the specified file type
	 * @param filetype The extension of the file to be read (e.g ".ext")
	 * @return a MoleculeReader that can read the file type, or null if none support it.
	 */
	public static MoleculeReader getReader(String filetype) {
		for(MoleculeReader r : readers) {
			if(r.supportedTypes().contains(filetype))
				return r;
		}
		
		return null;
	}
	
	/**
	 * Gets a MoleculeWriter capable of writing to the specified file type
	 * @param filetype The extension of the file to be read (e.g ".ext")
	 * @return a MoleculeWriter that can write to the file type, or null if none support it.
	 */
	public static MoleculeWriter getWriter(String filetype) {
		for(MoleculeWriter w : writers) {
			if(w.supportedTypes().contains(filetype))
				return w;
		}
		
		return null;
	}
}
